package com.yami.shop.search.common.util;

import com.yami.shop.bean.bo.ProductBO;
import com.yami.shop.bean.enums.ProdStatusEnums;
import com.yami.shop.common.util.Json;
import com.yami.shop.search.common.constant.EsIndexEnum;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.script.Script;
import org.elasticsearch.xcontent.XContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @author YXF
 * @date 2021/07/29
 */
@Component
public class EsSearchProdUtil {

    private static final Logger log = LoggerFactory.getLogger(EsSearchProdUtil.class);

    /**
     * 正常来说普通方法才是属于实体对象（也就是New出来的对象）的，spring注入是在容器中实例化对象，静态变量是无法注入的
     * 所以需要通过构造方法的方式来进行注入，或者使用@PostConstruct注解
     */

    public static void save(Long id, ProductBO productBO) {
        save(id, productBO, EsIndexEnum.PRODUCT.value());
    }

    public static void save(Long id, ProductBO productBO, String esIndex) {
        if (Objects.isNull(productBO)) {
            return;
        }
        IndexRequest request = new IndexRequest(esIndex)
                .id(productBO.getIndexIdPrefix() + String.valueOf(id))
                .source(Objects.requireNonNull(Json.toJsonString(productBO)), XContentType.JSON);
        EsSearchUtil.save(request);
    }

    public static void saveBatch(Map<Long, ProductBO> map) {
        saveBatch(map, EsIndexEnum.PRODUCT.value());
    }

    public static void saveBatch(Map<Long, ProductBO> map, String esIndex) {
        if (map.size() == 0) {
            return;
        }
        BulkRequest request = new BulkRequest();
        for (Long id : map.keySet()) {
            IndexRequest indexRequest = new IndexRequest(esIndex);
            indexRequest.id(map.get(id).getIndexIdPrefix() + String.valueOf(id));
            indexRequest.source(Objects.requireNonNull(Json.toJsonString(map.get(id))), XContentType.JSON);
            request.add(indexRequest);
        }
        EsSearchUtil.saveBatch(request);
    }

    public static void update(ProductBO productBO) {
        update(productBO, EsIndexEnum.PRODUCT.value());
    }

    public static void update(ProductBO productBO, String esIndex) {
        delete(productBO.getIndexIdPrefix() + String.valueOf(productBO.getProdId()));
        save(productBO.getProdId(), productBO, esIndex);
    }

    public static void partialUpdate(ProductBO productBO) {
        partialUpdate(productBO, EsIndexEnum.PRODUCT.value());
    }

    public static void partialUpdate(ProductBO productBO, String esIndex) {
        if (Objects.equals(productBO.getStatus(), ProdStatusEnums.DELETE.getValue())) {
            delete(productBO.getIndexIdPrefix() + String.valueOf(productBO.getProdId()));
            return;
        }
        if (Objects.isNull(productBO)) {
            return;
        }
        UpdateRequest request = new UpdateRequest(esIndex, productBO.getIndexIdPrefix() + String.valueOf(productBO.getProdId()))
                .doc(Json.toJsonString(productBO), XContentType.JSON);
        EsSearchUtil.partialUpdate(request);
    }

    public static void updateBatch(Map<Long, ProductBO> map) {
        updateBatch(map, EsIndexEnum.PRODUCT.value());
    }

    public static void updateBatch(Map<Long, ProductBO> map, String esIndex) {
        List<String> ids = new ArrayList<String>();
        for (Map.Entry<Long, ProductBO> entry : map.entrySet()){
            ids.add(entry.getValue().getIndexIdPrefix()+entry.getKey());
        }
        deleteBatch(ids);
        saveBatch(map, esIndex);
    }

    public static void updateStockByPainless(Map<String, Script> prodMap) {
        updateStockByPainless(prodMap, EsIndexEnum.PRODUCT.value());
    }

    public static void updateStockByPainless(Map<String, Script> prodMap, String esIndex) {
        BulkRequest request = new BulkRequest();
        prodMap.forEach( (prodId, script) -> {
            UpdateRequest updateRequest = new UpdateRequest(esIndex, String.valueOf(prodId));
            updateRequest.script(script);
            request.add(updateRequest);
        });
        EsSearchUtil.updateStockByPainless(request);
    }

    public static void delete(String id) {
        // 删除数据
        EsSearchUtil.delete(id, EsIndexEnum.PRODUCT.value());
    }
    public static void deleteBatch(Collection<String> ids) {
        EsSearchUtil.deleteBatch(ids, EsIndexEnum.PRODUCT.value(),"prodId");
    }
}
